package com.egreen.admin.utils;


import com.egreen.admin.common.exception.JwtFormatException;
import com.egreen.admin.common.exception.JwtNotFoundException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author cloudJiang
 * @date 2022/8/17 0:25
 */

@Component
public class JwtUtil {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /**
     * redis存储的前缀
     */
    private static String KEY_CODE = "token:admin:";

    /**
     * 三个小时的毫秒数
     * 加密签名
     */
    private static long EXPIRE = 60 * 60 * 1000 * 3;
    private static String APP_SECRET = "e-GreenRecycling-Admin";

    /**
     * 登录时创建token并返回，过程中将token存入redis
     *
     * @param id
     * @param role 用户角色，传入状态码即可
     * @return 生成的token
     */
    public String createTokenWhenLogin(Integer id, Integer role) {
        String token = Jwts.builder()
                //令牌类型
                .setHeaderParam("typ", "JWT")
                //签名算法
                .setHeaderParam("alg", "HS256")
                //令牌主题
                .setSubject("Login")
                //签发时间
                .setIssuedAt(new Date())
                //过期时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                //存储信息
                .claim("adminId", id)
                .claim("adminRole", role)
                //签名方式
                .signWith(SignatureAlgorithm.HS256, APP_SECRET).compact();

        //将token存储入redis中
        redisTemplate.opsForValue().set(KEY_CODE + id, token);
        return token;
    }

    /**
     * 校验jwt,解析后首先检查redis中是否存在该token,存在则将传入的jwt返回
     *
     * @param jwtToken
     * @return
     */

    public Object checkAdminJwt(String jwtToken) {
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        if (claimsJws == null) {
            throw new JwtFormatException();
        }
        Object adminId = claimsJws.getBody().get("adminId");
        String key = KEY_CODE + adminId;
        //若redis中不存在该记录则抛出异常
        if (!redisTemplate.hasKey(key)) {
            throw new JwtNotFoundException();
        }
        return claimsJws.getBody();
    }

    /**
     * 用户退出登录时调用此方法将存储的token在这里删除
     *
     * @param id
     */

    public void deleteJwtFromRedis(Object id) {
        redisTemplate.delete(KEY_CODE + id);
    }

}
